package com.wmx.jdk8;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.wmx.apachestudy.pojo.Person;
import org.junit.Test;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * java.util.stream.Collectors :一个有实现{@link Collector} 有用的工具类
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2021/6/11 21:54
 */
@SuppressWarnings("all")
public class CollectorsTest {

    /**
     * java.util.stream.Collectors :一个有实现{@link Collector} 有用的工具类
     * toList(): 流转 List，还有 toSet()、toMap 等
     */
    @org.junit.Test
    public void toSet1() {
        List<String> list = Arrays.asList("a", "b", "c", "d", "e");
        Set<String> collect = list.stream().collect(Collectors.toSet());
        // a b c d e
        collect.stream().forEach(item -> System.out.print(item + " "));
    }

    @Test
    public void toSet2() {
        // [{c21=新增, address=深圳市, agency_code=201025, age=30},
        // {c21=既往, address=长沙市, agency_code=002015, age=44},
        // {c21=删除, address=武汉市, agency_code=304100, age=87},
        // {c21=既往, address=深圳市, agency_code=324100, age=null}}
        List<Map<String, Object>> dataList = getDataList();

        Set<String> agencyCodeSet = dataList.stream().
                map(item -> String.valueOf(item.get("agency_code"))).
                collect(Collectors.toSet());
        // [002015, 304100, 324100, 201025]
        System.out.println(agencyCodeSet);
    }

    /**
     * toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper)
     * 1、将流转为 Map，它的 key 和 value 是将提供的映射函数应用于输入元素的结果。
     * 2、如果转换后的 key 有重复，则抛出 java.lang.IllegalStateException: Duplicate key，此时推荐使用 {@link #toMap(Function, Function, BinaryOperator)}
     * 3、转换时，key 和 value 都不允许为 null，否则空指针异常。
     */
    @Test
    public void toMap1() {
        // [{c21=新增, address=深圳市, agency_code=201025, age=30},
        // {c21=既往, address=长沙市, agency_code=002015, age=44},
        // {c21=删除, address=武汉市, agency_code=304100, age=87},
        // {c21=既往, address=深圳市, agency_code=324100, age=null}}
        List<Map<String, Object>> dataList = getDataList();

        // toMap 的 key 和 value 不允许为 null，否则空指针异常
        // toMap 的 key 不允许重复，否则 IllegalStateException
        Map<String, Object> collect = dataList.stream()
                .collect(Collectors.toMap(t -> t.get("agency_code").toString(), t -> t.get("age") == null ? "" : t.get("age")));
        // {002015=44, 304100=87, 324100=, 201025=30}
        System.out.println(collect);
    }

    /**
     * toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction)
     * 1、如果 key 复制，则使用提供的合并函数进行合并。
     * 2、BinaryOperator 合并方式介绍如下：
     * * (previous, next) -> next)：表示取后面的覆盖前面的；
     * * (previous, next) -> previous)：表示不覆盖.
     * * (previous, next) -> previous + "," + next)：表示使用逗号连接
     */
    @Test
    public void toMap2() {
        // [{c21=新增, address=深圳市, agency_code=201025, age=30},
        // {c21=既往, address=长沙市, agency_code=002015, age=44},
        // {c21=删除, address=武汉市, agency_code=304100, age=87},
        // {c21=既往, address=深圳市, agency_code=324100, age=null}}
        List<Map<String, Object>> dataList = getDataList();

        // toMap 的 key 和 value 不允许为 null，否则空指针异常
        // toMap 的 key 如果重复，则使用逗号进行连接.
        Map<String, String> collect = dataList.stream()
                .collect(Collectors.toMap(t -> t.get("c21").toString(), t -> t.get("agency_code").toString(), (previous, next) -> previous + "," + next));
        // {既往=002015,324100, 新增=201025, 删除=304100}
        System.out.println(collect);
    }

    /**
     * toMap(Function<? super T, ? extends K> keyMapper,
     * Function<? super T, ? extends U> valueMapper,
     * BinaryOperator<U> mergeFunction,
     * Supplier<M> mapSupplier)
     * 1、mapSupplier：默认返回的是 HashMap，可以使用 mapSupplier 指定返回的 map 类型.
     */
    @Test
    public void toMap3() {
        // [{c21=新增, address=深圳市, agency_code=201025, age=30},
        // {c21=既往, address=长沙市, agency_code=002015, age=44},
        // {c21=删除, address=武汉市, agency_code=304100, age=87},
        // {c21=既往, address=深圳市, agency_code=324100, age=null}}
        List<Map<String, Object>> dataList = getDataList();

        // toMap 的 key 和 value 不允许为 null，否则空指针异常
        // toMap 的 key 如果重复，则使用逗号进行连接.
        Map<String, String> map = dataList.stream()
                .collect(Collectors.toMap(
                        t -> t.get("c21").toString(),
                        t -> t.get("agency_code").toString(),
                        (previous, next) -> previous + "," + next,
                        LinkedHashMap::new));
        // {新增=201025, 既往=002015,324100, 删除=304100}
        System.out.println(map);
    }

    @Test
    public void toMap4() {
        // {update_time=2022-01-01 00:00:00, c21=新增, address=深圳市, agency_code=201025, age=30},
        // {update_time=2022-03-01 00:00:00, c21=既往, address=长沙市, agency_code=002015, age=44},
        // {update_time=2021-03-01 00:00:00, c21=删除, address=武汉市, agency_code=304100, age=87},
        // {update_time=2020-03-01 00:00:00, c21=既往, address=深圳市, agency_code=324100, age=null}

        List<Map<String, Object>> dataList = getDataList();

        // toMap 的 key 和 value 不允许为 null，否则空指针异常
        // toMap 的 key 如果重复，则按更新时间取最后更新的数据.
        Map<String, Map<String, Object>> collect = dataList.stream()
                .collect(Collectors.toMap(
                        t -> t.get("c21").toString(),
                        t -> t,
                        (previous, next) -> {
                            Date nextDate = (Date) next.get("update_time");
                            Date previouDate = (Date) previous.get("update_time");
                            if (nextDate.compareTo(previouDate) > 0) {
                                return next;
                            } else {
                                return previous;
                            }
                        }));
        // {
        // 既往={update_time=2022-03-01 00:00:00, c21=既往, address=长沙市, agency_code=002015, age=44},
        // 新增={update_time=2022-01-01 00:00:00, c21=新增, address=深圳市, agency_code=201025, age=30},
        // 删除={update_time=2021-03-01 00:00:00, c21=删除, address=武汉市, agency_code=304100, age=87}
        // }
        System.out.println(collect);
    }

    /**
     * 分组求合计
     */
    @Test
    public void toMap5() {
        // {update_time=2022-01-01 00:00:00, c21=新增, address=深圳市, agency_code=201025, age=30},
        // {update_time=2022-03-01 00:00:00, c21=既往, address=长沙市, agency_code=002015, age=44},
        // {update_time=2021-03-01 00:00:00, c21=删除, address=武汉市, agency_code=304100, age=87},
        // {update_time=2020-03-01 00:00:00, c21=既往, address=深圳市, agency_code=324100, age=null}

        List<Map<String, Object>> dataList = getDataList();

        // toMap 的 key 和 value 不允许为 null，否则空指针异常
        Map<String, Map<String, Object>> collect = dataList.stream()
                .collect(Collectors.toMap(
                        t -> t.get("c21").toString(),
                        t -> t,
                        (previous, next) -> {
                            BigDecimal bigDecimal1 = new BigDecimal(StrUtil.blankToDefault(MapUtil.getStr(previous, "agency_code"), "0"));
                            BigDecimal bigDecimal2 = new BigDecimal(StrUtil.blankToDefault(MapUtil.getStr(next, "agency_code"), "0"));
                            previous.put("agency_code", bigDecimal1.add(bigDecimal2).toString());
                            return previous;
                        }));
        // {
        // 既往={update_time=2022-03-01 00:00:00, c21=既往, address=长沙市, agency_code=326115, age=44},
        // 新增={update_time=2022-01-01 00:00:00, c21=新增, address=深圳市, agency_code=201025, age=30},
        // 删除={update_time=2021-03-01 00:00:00, c21=删除, address=武汉市, agency_code=304100, age=87}
        // }
        System.out.println(collect);
    }

    @Test
    public void toMap6() {
        List<Person> personList = new ArrayList<>();
        Person person1 = new Person(1, "张三", DateUtil.parse("1993/08/25"), 7888.89f);
        Person person2 = new Person(2, "李四", DateUtil.parse("1994/08/21"), -5688.71f);
        Person person3 = new Person(3, "王五", DateUtil.parse("1995/08/15"), 8588.53f);
        Person person4 = new Person(4, "马六", DateUtil.parse("1991/06/13"), 100F);
        Person person5 = new Person(4, "马六", DateUtil.parse("1992/04/05"), 1288.35f);
        personList.add(person1);
        personList.add(person2);
        personList.add(person3);
        personList.add(person4);
        personList.add(person5);

        final Map<Integer, Float> collect1 = personList.stream().collect(Collectors.toMap(Person::getId, Person::getSalary, (pre, next) -> pre + next));
        final Map<Integer, Float> collect2 = personList.stream().collect(Collectors.toMap(Person::getId, Person::getSalary, Float::sum));
        System.out.println(collect1); // {1=7888.89, 2=-5688.71, 3=8588.53, 4=1388.35}
        System.out.println(collect2); // {1=7888.89, 2=-5688.71, 3=8588.53, 4=1388.35}
    }

    /**
     * Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
     * 1、对元流中的元素进行分组，值相同的视作为一组
     */
    @org.junit.Test
    public void groupingBy1() {
        // 元素不能有 null，否则：java.lang.NullPointerException: element cannot be mapped to a null key
        Map<Integer, List<Integer>> integerListMap = Stream.of(1, 3, 23, 45, 32, 12, 44, 45, 32, 3, 3).collect(Collectors.groupingBy(item -> item));
        //{32=[32, 32], 1=[1], 3=[3, 3, 3], 23=[23], 44=[44], 12=[12], 45=[45, 45]}
        System.out.println(integerListMap);
    }

    /**
     * Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
     * 1、对元流中的元素进行分组.
     * 2、分组的元素值不能为 null，否则：java.lang.NullPointerException: element cannot be mapped to a null key
     * 3、如果原始的流没有数据，则得到的结果是个空对象，不会是null，不用担心空指针异常。
     */
    @Test
    public void groupingBy2() {
        List<Map<String, Object>> dataList = this.getDataList();
        /**
         * [{c21=新增, address=深圳市, agency_code=201025},
         * {c21=既往, address=长沙市, agency_code=002015},
         * {c21=删除, address=武汉市, agency_code=304100},
         * {c21=既往, address=深圳市, agency_code=324100}]
         */
        System.out.println(dataList);

        // 1、根据 c21 的值进行分组，c21 值相同的元素作为一组
        // 2、item.get 的值不能为 null，否则：java.lang.NullPointerException: element cannot be mapped to a null key
        // 3、如果 dataList 是个空集合，则得到的结果是个空Map，不会是null。
        Map<Object, List<Map<String, Object>>> objectListMap = dataList.stream().collect(Collectors.groupingBy(item -> item.get("c21")));
        /**
         * {既往=[{c21=既往, address=长沙市, agency_code=002015}, {c21=既往, address=深圳市, agency_code=324100}],
         * 新增=[{c21=新增, address=深圳市, agency_code=201025}],
         * 删除=[{c21=删除, address=武汉市, agency_code=304100}]}
         */
        System.out.println(objectListMap);
    }

    /**
     * Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
     * 1、对元流中的元素进行分组
     */
    @Test
    public void groupingBy3() {
        List<Map<String, Object>> dataList = this.getDataList();

        Map<String, List<Map<String, Object>>> collect = dataList.stream().collect(Collectors.groupingBy(map -> {
            Optional<Object> c22 = Optional.ofNullable(map.get("age"));
            if (Integer.parseInt(c22.orElse("0") + "") < 30) {
                return "少年";
            } else if (Integer.parseInt(c22.orElse("0") + "") < 60) {
                return "中年";
            } else {
                return "老年";
            }
        }));

        /**
         * {老年=[{c21=删除, address=武汉市, agency_code=304100, age=87}, {c21=既往, address=深圳市, agency_code=324100, age=90}],
         * 中年=[{c21=新增, address=深圳市, agency_code=201025, age=30}, {c21=既往, address=长沙市, agency_code=002015, age=44}]}
         */
        System.out.println(collect);
    }

    @Test
    public void groupingBy4() {
        List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
        // 将一组单词按照首字母进行分组
        Map<Character, List<String>> groupByFirstLetter = words.stream().collect(Collectors.groupingBy(s -> s.charAt(0)));
        // 输出结果为 {a=[apple], b=[banana], c=[cherry], d=[date], e=[elderberry]}
        System.out.println(groupByFirstLetter);
    }

    /**
     * partitioningBy 操作用于将集合中的元素按照指定的条件进行分区，分为满足条件和不满足条件两部分。
     * 它通过传递一个 Predicate 接口的 Lambda表 达式作为参数来实现分区条件。
     */
    @Test
    public void partitioningBy1() {
        // Map<Boolean,List<Integer>>
        Map<Boolean, List<Integer>> collect = Stream.of(0, 1, 0, 1).collect(Collectors.partitioningBy(integer -> integer == 0));
        // {false=[1, 1], true=[0, 0]}
        System.out.println(collect);

        // Map<Boolean,Set<Integer>>
        // 自定义下游收集器
        Map<Boolean, Set<Integer>> collect1 = Stream.of(0, 1, 0, 1).collect(Collectors.partitioningBy(integer -> integer == 0, Collectors.toSet()));
        // {false=[1], true=[0]}
        System.out.println(collect1);

        List<Map<String, Object>> dataList = this.getDataList();
        // {update_time=2022-01-01 00:00:00, c21=新增, address=深圳市, agency_code=201025, age=30}
        // {update_time=2022-03-01 00:00:00, c21=既往, address=长沙市, agency_code=002015, age=44}
        // {update_time=2021-03-01 00:00:00, c21=删除, address=武汉市, agency_code=304100, age=87}
        // {update_time=2020-03-01 00:00:00, c21=既往, address=深圳市, agency_code=324100, age=null}
        dataList.stream().forEach(item -> System.out.println(item));

        // 提取出删除和其他单位
        Map<Boolean, List<Map<String, Object>>> listMap = dataList.stream().collect(Collectors.partitioningBy(map -> "删除".equals(map.get("c21"))));
        /**
         * {
         * false=[{update_time=2022-01-01 00:00:00, c21=新增, address=深圳市, agency_code=201025, age=30},
         *      {update_time=2022-03-01 00:00:00, c21=既往, address=长沙市, agency_code=002015, age=44},
         *      {update_time=2020-03-01 00:00:00, c21=既往, address=深圳市, agency_code=324100, age=null}],
         * true=[{update_time=2021-03-01 00:00:00, c21=删除, address=武汉市, agency_code=304100, age=87}]
         * }
         */
        System.out.println(listMap);
    }

    @Test
    public void partitioningBy2() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        // 将一组数字按照是否为偶数进行分区
        Map<Boolean, List<Integer>> partitionByEven = numbers.stream().collect(Collectors.partitioningBy(n -> n % 2 == 0));
        // 输出结果为 {false=[1, 3, 5], true=[2, 4]}
        System.out.println(partitionByEven);
    }

    /**
     * Collector<CharSequence, ?, String> joining(CharSequence delimiter)：将元素按遇到顺序 用指定的分隔符 连接起来
     */
    @Test
    public void joining1() {
        List<String> stringList = Arrays.asList("12H", "43D", "78G", null, "909I");
        String collect = "'" + stringList.stream().collect(Collectors.joining("','")) + "'";
        //'12H','43D','78G','null','909I'
        System.out.println(collect);
    }

    /**
     * Collector<CharSequence, ?, String> joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
     * 将元素按遇到顺序 用指定的分隔符 连接起来，并指定开头与结尾的连接符
     */
    @Test
    public void joining2() {
        List<String> stringList = Arrays.asList("121H", "431D", "728G", null, "9309I");
        String collect = stringList.stream().collect(Collectors.joining("','", "'", "'"));
        //'121H','431D','728G','null','9309I'
        System.out.println(collect);
    }

    /**
     * <T> Collector<T, ?, Long> counting()：统计输入元素的数量。如果不存在元素，则结果为0。
     */
    @Test
    public void counting() {
        List<String> stringList = Arrays.asList("121H", "431D", "728G", null, "9309I");
        Long counting = stringList.stream().collect(Collectors.counting());
        System.out.println(counting);// 5
    }

    /**
     * <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator) ：通过比较器获取最大值
     * <T> Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator) ：通过比较器获取最小值
     */
    @Test
    public void maxBy() {
        List<Integer> integerList1 = Arrays.asList(1, 0, -10, 9, 8, 100, 200, -80);
        // 获取集合中的最大值，不存在时返回 0
        Optional<Integer> optionalInteger = integerList1.stream().collect(Collectors.maxBy(Comparator.naturalOrder()));
        System.out.println(optionalInteger.orElse(0));// 200

        // 获取集合中的最小值，不存在时返回 0，Collectors.minBy、Collectors.maxBy 排序取值時，元素不能為 null，否则异常
        List<Integer> integerList2 = Arrays.asList(1, 0, -10, 9, null, 100, 200, -80);
        Integer integer = integerList2.stream().filter(item -> Optional.ofNullable(item).isPresent()).collect(Collectors.minBy(Comparator.naturalOrder())).orElse(0);
        System.out.println(integer);//-80
    }

    @Test
    public void minBy() {
        List<Integer> numbers = Arrays.asList(5, 2, 8, 3, 1);
        Optional<Integer> minNumber = numbers.stream().collect(Collectors.minBy(Comparator.naturalOrder()));
        // 输出结果为：Optional[1]
        System.out.println(minNumber);
    }

    /**
     * <T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper)	对整数元素求和，如果不存在值，则返回 0
     * <T> Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper) 对长整数元素求和，如果不存在值，则返回 0
     * <T> Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper) 对浮点型元素求和，如果不存在值，则返回 0
     */
    @Test
    public void summingInt() {
        Integer collect = Stream.of(1, 22, 14, 25, 34, 33, 55, 43).collect(Collectors.summingInt(integer -> Integer.valueOf(integer)));
        System.out.println(collect);// 227

        Double collect2 = Stream.of(11.2, 34.3, 34.3, 55.0).collect(Collectors.summingDouble(Double::doubleValue));
        System.out.println(collect2);// 134.8
    }

    /**
     * <T> Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)：对 int 整型求摘要统计信息，包含：
     * getCount()：元素个数
     * getSum()：求和
     * getMin()：最小值
     * getAverage()：平均值
     * getMax())：最大值
     * Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)
     * Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper)
     */
    @Test
    public void summarizingInt() {
        IntSummaryStatistics intSummaryStatistics = Stream.of(1, 22, 14, 25, 34, 33, 55, 43).collect(Collectors.summarizingInt(Integer::intValue));
        System.out.println(intSummaryStatistics);// IntSummaryStatistics{count=8, sum=227, min=1, average=28.375000, max=55}
        System.out.println(intSummaryStatistics.getSum());// 227

        DoubleSummaryStatistics summaryStatistics = Stream.of(11.2, 34.3, 34.3, 55.0).collect(Collectors.summarizingDouble(dou -> dou.doubleValue()));
        System.out.println(summaryStatistics);// DoubleSummaryStatistics{count=4, sum=134.800000, min=11.200000, average=33.700000, max=55.000000}
        System.out.println(summaryStatistics.getAverage());// 33.7
    }

    /**
     * 求元素的平均值
     * Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper)
     * Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper)
     * Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper)
     */
    @Test
    public void averagingLong() {
        Double collect1 = Stream.of(1, 22, 14, 25, 34, 33, 55, 43).collect(Collectors.averagingLong(l -> l.longValue()));
        System.out.println(collect1);// 28.375

        Double collect2 = Stream.of(11.2, 34.3, 34.3, 55.0).collect(Collectors.averagingDouble(d -> d.doubleValue()));
        System.out.println(collect2);// 33.7
    }

    /**
     * Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op)，内部函数方法 R apply(T t, U u)
     * apply 方法中的参数 t 表示当前计算的值，u 表示下一个元素，返回的值 r 会作为参数 t 继续传入，非常适合累加、累乘等等操作
     * Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op): identity 定义默认值，当没有元素时返回的值
     * Collector<T, ?, U> reducing(U identity,Function<? super T, ? extends U> mapper,BinaryOperator<U> op)
     * mapper：应用于每个输入值的映射函数
     */
    @Test
    public void reducing() {
        // 累加操作，
        Integer integer = Stream.of(1, 22, 14, 25, 34, 33, 55, 43).collect(Collectors.reducing((i, j) -> i + j)).orElse(0);
        System.out.println(integer);// 227

        List<Map<String, Object>> dataList = this.getDataList();
        /**
         * [{c21=新增, address=深圳市, agency_code=201025, age=30},
         * {c21=既往, address=长沙市, agency_code=002015, age=44},
         * {c21=删除, address=武汉市, agency_code=304100, age=87},
         * {c21=既往, address=深圳市, agency_code=324100, age=90}]
         */
        System.out.println(dataList);

        // 求年龄之和
        Integer collect = dataList.stream().map(item -> (Integer) item.get("age")).collect(Collectors.reducing(0, (i, j) -> i + j));
        System.out.println(collect);// 251

        // 求年龄之和
        Integer age = dataList.stream().collect(Collectors.reducing(0, item -> (Integer) ((Map) item).get("age"), (i, j) -> i + j));
        System.out.println(age);// 251
    }


    private List<Map<String, Object>> getDataList() {
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>(8);
        Map<String, Object> map2 = new HashMap<>(8);
        Map<String, Object> map3 = new HashMap<>(8);
        Map<String, Object> map4 = new HashMap<>(8);

        map1.put("c21", "新增");
        map1.put("agency_code", "201025");
        map1.put("address", "深圳市");
        map1.put("age", 30);
        map1.put("update_time", DateUtil.parseDate("2022-01-01"));

        map2.put("c21", "既往");
        map2.put("agency_code", "002015");
        map2.put("address", "长沙市");
        map2.put("age", 44);
        map2.put("update_time", DateUtil.parseDate("2022-03-01"));

        map3.put("c21", "删除");
        map3.put("agency_code", "304100");
        map3.put("address", "武汉市");
        map3.put("age", 87);
        map3.put("update_time", DateUtil.parseDate("2021-03-01"));

        map4.put("c21", "既往");
        map4.put("agency_code", "324100");
        map4.put("address", "深圳市");
        map4.put("age", null);
        map4.put("update_time", DateUtil.parseDate("2020-03-01"));

        dataList.add(map1);
        dataList.add(map2);
        dataList.add(map3);
        dataList.add(map4);

        return dataList;
    }

    /**
     * 对 List<Map<String,Object>> 数据去重.
     */
    @Test
    public void testCollectingAndThen() {
        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("agency_id", "20791");
        map.put("agency_name", "单位1");
        map.put("agency_codee", "001001");
        list.add(new HashMap<>(map));
        map.put("agency_id", "20792");
        map.put("agency_name", "单位2");
        map.put("agency_codee", "001002");
        list.add(new HashMap<>(map));
        map.put("agency_id", "20793");
        map.put("agency_name", "单位3");
        map.put("agency_codee", "001003");
        list.add(new HashMap<>(map));
        map.put("agency_id", "20792");
        map.put("agency_name", "单位21");
        map.put("agency_codee", "001002");
        list.add(new HashMap<>(map));

        // {agency_codee=001001, agency_id=20791, agency_name=单位1},
        // {agency_codee=001002, agency_id=20792, agency_name=单位2},
        // {agency_codee=001003, agency_id=20793, agency_name=单位3},
        // {agency_codee=001002, agency_id=20792, agency_name=单位21}
        System.out.println("去重前：" + list);

        // 根据单位ID进行去重，如果单位ID为null，则直接会被过滤掉.
        list = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing((o) -> o.get("agency_id")))), ArrayList::new));

        // {agency_codee=001001, agency_id=20791, agency_name=单位1},
        // {agency_codee=001002, agency_id=20792, agency_name=单位2},
        // {agency_codee=001003, agency_id=20793, agency_name=单位3}
        System.out.println("去重后：" + list);
    }


}
